package dao

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"io"
	"net/http"
	"user-srv/basic/config"
	"user-srv/basic/inits"
	"user-srv/handler/models"
	"user-srv/pkg"
)

// MatchRequest 人脸比对请求参数（支持1-10张人脸）
type MatchRequest []struct {
	Image           string `json:"image"`            // 人脸Base64编码
	ImageType       string `json:"image_type"`       // 固定为"BASE64"
	QualityControl  string `json:"quality_control"`  // 图片质量控制（如"NORMAL"）
	LivenessControl string `json:"liveness_control"` // 活体检测控制（如"NONE"）
}

// MatchResponse 人脸比对响应结果
type MatchResponse struct {
	ErrorCode int    `json:"error_code"`
	ErrorMsg  string `json:"error_msg"`
	LogId     int64  `json:"log_id"`
	Timestamp int64  `json:"timestamp"`
	Result    struct {
		Score     float64 `json:"score"`     // 相似度（0-100）
		Threshold float64 `json:"threshold"` // 推荐匹配阈值
		FaceList  []struct {
			FaceToken string `json:"face_token"` // 人脸特征令牌
		} `json:"face_list"`
	} `json:"result"`
}

// FaceMatch 执行人脸比对（封装请求、响应解析）
func FaceMatch(accessToken string, req MatchRequest) (*MatchResponse, error) {
	url := fmt.Sprintf("https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=%s", accessToken)
	jsonData, err := json.Marshal(req)
	if err != nil {
		return nil, fmt.Errorf("序列化请求失败: %w", err)
	}

	httpReq, err := http.NewRequest("POST", url, bytes.NewReader(jsonData))
	if err != nil {
		return nil, fmt.Errorf("创建请求失败: %w", err)
	}
	httpReq.Header.Set("Content-Type", "application/json")

	resp, err := config.App.BaiduFace.Client.Do(httpReq)
	if err != nil {
		return nil, fmt.Errorf("发送请求失败: %w", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应失败: %w", err)
	}

	var matchResp MatchResponse
	if err := json.Unmarshal(body, &matchResp); err != nil {
		return nil, fmt.Errorf("解析响应失败: %w，原始内容: %s", err, string(body))
	}

	if matchResp.ErrorCode != 0 {
		return nil, fmt.Errorf("比对失败 [Code:%d]: %s", matchResp.ErrorCode, matchResp.ErrorMsg)
	}

	return &matchResp, nil
}

// ImageToBase64 将图片转换为Base64编码（通用工具）
func ImageToBase64(imgURL string) (string, error) {
	resp, err := http.Get(imgURL)
	if err != nil {
		return "", fmt.Errorf("下载图片失败: %v", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("图片下载失败，状态码: %d", resp.StatusCode)
	}

	imgData, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取图片数据失败: %v", err)
	}

	return base64.StdEncoding.EncodeToString(imgData), nil
}

// Face 人脸比对主逻辑（调用方无需关心图片来源）
func Face(face_img string) (int, error) {
	// 1. 初始化客户端
	inits.NewBaiduFaceClient()
	// 2. 获取AccessToken
	accessToken, err := pkg.GetAccessToken()
	if err != nil {
		fmt.Println("AccessToken获取失败" + err.Error())
		return 0, err
	}
	// 3. 按 user_id 查询数据库中的人脸（注册的人脸）
	var face models.Face
	face.FaceImg = face_img // 设置用户ID，用于查询
	if err := face.GetFace(); err != nil {
		fmt.Println("查找用户人脸失败")
		return 0, err
	}
	fmt.Println(face.UserId)
	// 4. 处理数据库中的人脸图片（注册的人脸）
	face1, err := ImageToBase64(face.FaceImg)
	if err != nil {
		fmt.Println("处理注册人脸失败")
		return 0, err
	}
	// 5. 处理传入的人脸图片（当前人脸）
	face2, err := ImageToBase64(face_img)
	if err != nil {
		fmt.Println("处理当前人脸失败")
		return 0, err
	}
	// 5. 构造比对请求
	reqData := MatchRequest{
		{Image: face1, ImageType: "BASE64", QualityControl: "NORMAL"},
		{Image: face2, ImageType: "BASE64", QualityControl: "NORMAL"},
	}
	// 6. 执行人脸比对
	matchResp, err := FaceMatch(accessToken, reqData)
	if err != nil {
		fmt.Println("人脸比对失败", err)
		return 0, err
	}

	// 7. 结果判断
	fmt.Printf("\n✅ 人脸比对结果：\n相似度: %.2f 分（阈值: %.2f 分）\n",
		matchResp.Result.Score, matchResp.Result.Threshold)
	if matchResp.Result.Score < matchResp.Result.Threshold {
		return 0, errors.New("人脸比对不匹配")
	}
	fmt.Println("结论：两张图片为同一人")
	fmt.Printf("图片1人脸令牌: %s\n图片2人脸令牌: %s\n",
		matchResp.Result.FaceList[0].FaceToken,
		matchResp.Result.FaceList[1].FaceToken)

	return int(face.UserId), nil
}
func AddFaceByUserId(userId int32, face_img string) error {
	// 1. 实例化模型
	Face := &models.Face{
		UserId:  userId,
		FaceImg: face_img,
	}
	// 2. 检查该用户是否已存在人脸记录
	err := Face.GetFaceByUserId()
	if err != nil {
		// 非记录不存在的错误（真正的数据库错误）
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			fmt.Println("查询用户人脸记录失败")
			return err
		}
		// 走到这里说明 err 是 gorm.ErrRecordNotFound，即用户暂无记录，可继续添加
	} else {
		// 3. 若记录存在，返回错误
		if Face.Id > 0 { // 确认查询到有效记录
			fmt.Println("用户已存在人脸记录，不允许重复添加")
			return errors.New("该用户已添加人脸信息，请勿重复操作")
		}
	}
	// 4. 记录不存在，执行添加
	if err := Face.AddFace(); err != nil {
		fmt.Println("新增用户人脸记录失败")
		return err
	}
	fmt.Println("用户人脸记录添加成功")
	return nil
}
func UpdateFace(userId int, face_img string) error {
	var Face models.Face
	Face.UserId = int32(userId)
	// 步骤1：检查用户是否已有未删除的人脸记录
	if err := Face.GetFaceByUserId(); err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			fmt.Println("用户未添加人脸信息，无法修改")
			return errors.New("用户未添加人脸信息，无法修改")
		}
		fmt.Println("查询用户人脸记录失败")
		return errors.New("查询用户人脸记录失败")
	}
	// 步骤2：若查询结果为空（ID为0，代表无有效记录）
	if Face.Id == 0 {
		fmt.Println("用户未添加人脸信息，无法修改")
		return errors.New("用户未添加人脸信息，无法修改")
	}
	// 步骤3：执行更新（仅更新 image 和 updated_at）
	Face.FaceImg = face_img
	err := Face.UpdateFace()
	if err != nil {
		fmt.Println("更改失败")
		return err
	}
	return nil
}
func DeletedFace(userId int) error {
	var Face models.Face
	Face.UserId = int32(userId)
	// 步骤1：检查用户是否已有未删除的人脸记录
	if err := Face.GetFaceByUserId(); err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			fmt.Println("用户未添加人脸信息")
			return errors.New("用户未添加人脸信息")
		}
		fmt.Println("查询用户人脸记录失败")
		return errors.New("查询用户人脸记录失败")
	}
	// 步骤2：若查询结果为空（ID为0，代表无有效记录）
	if Face.Id == 0 {
		fmt.Println("用户未添加人脸信息")
		return errors.New("用户未添加人脸信息")
	}
	// 步骤3：执行更新（仅更新 image 和 updated_at）
	err := Face.DeletedFace()
	if err != nil {
		fmt.Println("删除失败")
		return err
	}
	return nil
}
